namespace WizardBase
{
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;

    using EFMLEditor.Properties;

    [Designer(typeof(WizardStepDesigner))]
    [ToolboxItem(false)]
    [DefaultEvent("Click")]
    public class StartStep : WizardStep
    {
        private Image iconImage;

        private ColorPair leftPair = new ColorPair(Color.Orange, Color.White, 270);

        private Image bindingImage;

        private string subtitle = "Enter a brief description of the wizard here.";

        private TextAppearence subtitleAppearence = new TextAppearence();

        private string title = "Welcome to the DemoWizard.";

        private TextAppearence titleAppearence = new TextAppearence();

        public StartStep()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.UserPaint, true);
#pragma warning disable DoNotCallOverridableMethodsInConstructor
            this.BackColor = SystemColors.ControlLightLight;
            this.Icon = Resources.icon;
            this.BindingImage = Resources.left;
            this.ResetSubtitleAppearence();
            this.ResetTitleAppearence();
            this.ResetLeftPair();
            this.leftPair.AppearenceChanged += this.leftPair_AppearenceChanged;
#pragma warning restore DoNotCallOverridableMethodsInConstructor
        }

        private void leftPair_AppearenceChanged(object sender, GenericEventArgs<bool> tArgs)
        {
            this.Invalidate();
        }

        protected void GetTextBounds(out RectangleF titleRect, out RectangleF subtitleRect)
        {
            Graphics graphics = this.CreateGraphics();
            try
            {
                this.GetTextBounds(out titleRect, out subtitleRect, graphics);
            }
            finally
            {
                if (graphics != null)
                {
                    graphics.Dispose();
                }
            }
        }

        protected virtual void GetTextBounds(out RectangleF titleRect, out RectangleF subtitleRect, Graphics graphics)
        {
            var format = new StringFormat(StringFormatFlags.FitBlackBox);
            format.Trimming = StringTrimming.EllipsisCharacter;
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            format.Trimming = StringTrimming.None;
            if (this.bindingImage != null)
            {
                SizeF sz = graphics.MeasureString(
                    this.Title, this.titleAppearence.Font, this.Width - this.bindingImage.Width, format);
                titleRect = new RectangleF(
                    this.bindingImage.Width + this.subtitleAppearence.Font.SizeInPoints,
                    this.subtitleAppearence.Font.SizeInPoints,
                    sz.Width,
                    sz.Height);
                SizeF sz1 = graphics.MeasureString(
                    this.Subtitle, this.subtitleAppearence.Font, this.Width - this.bindingImage.Width, format);
                subtitleRect = new RectangleF(
                    this.bindingImage.Width + this.subtitleAppearence.Font.SizeInPoints,
                    titleRect.Height + this.subtitleAppearence.Font.SizeInPoints,
                    sz1.Width,
                    sz1.Height);
            }
            else
            {
                SizeF sz = graphics.MeasureString(
                    this.Title, this.titleAppearence.Font, this.Width - this.LeftRectangle.Width, format);
                titleRect = new RectangleF(
                    this.LeftRectangle.Width + this.subtitleAppearence.Font.SizeInPoints,
                    this.subtitleAppearence.Font.SizeInPoints,
                    sz.Width,
                    sz.Height);
                SizeF sz1 = graphics.MeasureString(
                    this.Subtitle, this.subtitleAppearence.Font, this.Width - this.LeftRectangle.Width, format);
                subtitleRect = new RectangleF(
                    this.LeftRectangle.Width + this.subtitleAppearence.Font.SizeInPoints,
                    titleRect.Height + this.subtitleAppearence.Font.SizeInPoints,
                    sz1.Width,
                    sz1.Height);
            }
        }

        protected Region GetTextBounds()
        {
            RectangleF titleRect;
            RectangleF subtitleRect;
            this.GetTextBounds(out titleRect, out subtitleRect);
            return this.GetTextBounds(titleRect, subtitleRect);
        }

        protected Region GetTextBounds(RectangleF titleRect, RectangleF subtitleRect)
        {
            if (titleRect.IsEmpty)
            {
                if (!subtitleRect.IsEmpty)
                {
                    return new Region(subtitleRect);
                }
                return new Region(RectangleF.Empty);
            }
            else
            {
                if (!subtitleRect.IsEmpty)
                {
                    return
                        new Region(
                            new RectangleF(172f, 8f, (this.Width - 180), (8f + titleRect.Height) + subtitleRect.Height));
                }
                return new Region(titleRect);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Rectangle rect;
            Rectangle iconRect;
            RectangleF titleRect;
            RectangleF subtitleRect;
            base.OnPaint(e);
            Graphics graphics = e.Graphics;
            rect = this.LeftRectangle;
            this.GetTextBounds(out titleRect, out subtitleRect);
            if (this.bindingImage != null)
            {
                graphics.DrawImage(this.bindingImage, rect);
                iconRect = this.IconRectangle;
                iconRect.Inflate(-1, -1);
                if (this.iconImage != null)
                {
                    graphics.DrawImage(this.iconImage, iconRect);
                }
            }
            else
            {
                using (
                    Brush brush = new LinearGradientBrush(
                        rect, this.leftPair.BackColor1, this.leftPair.BackColor2, this.leftPair.Gradient))
                {
                    graphics.FillRectangle(brush, rect);
                    iconRect = this.IconRectangle;
                    iconRect.Inflate(-1, -1);
                    if (this.iconImage != null)
                    {
                        graphics.DrawImage(this.iconImage, iconRect);
                    }
                }
            }
            this.DrawText(graphics, titleRect, this.title, this.titleAppearence);
            this.DrawText(graphics, subtitleRect, this.subtitle, this.subtitleAppearence);
        }

        internal override void Reset()
        {
            this.ResetLeftPair();
            this.ResetBindingImage();
            this.ResetIcon();
            this.BackColor = SystemColors.ControlLightLight;
            this.BackgroundImage = null;
            this.BackgroundImageLayout = ImageLayout.Tile;
            this.ForeColor = SystemColors.ControlText;
            this.Title = "Welcome to the DemoWizard.";
            this.Subtitle = "Enter a brief description of the wizard here.";
        }

        [DefaultValue(typeof(Color), "ControlLightLight")]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }

        [Description("The sub title appearence of step.")]
        [Category("Appearance")]
        public TextAppearence SubtitleAppearence
        {
            get
            {
                return this.subtitleAppearence;
            }
            set
            {
                if (this.subtitleAppearence != value)
                {
                    this.subtitleAppearence = value;
                    this.Invalidate();
                }
            }
        }

        [Description("The title font of step.")]
        [Category("Appearance")]
        public TextAppearence TitleAppearence
        {
            get
            {
                return this.titleAppearence;
            }
            set
            {
                if (this.titleAppearence != value)
                {
                    this.titleAppearence = value;
                    this.Invalidate();
                }
            }
        }

        [Description("The icon image of the step.")]
        [Category("Appearance")]
        public virtual Image Icon
        {
            get
            {
                return this.iconImage;
            }
            set
            {
                if (value != this.iconImage)
                {
                    this.iconImage = value;
                    this.Invalidate();
                }
            }
        }

        protected virtual Rectangle IconRectangle
        {
            get
            {
                return new Rectangle(104, 12, 48, 48);
            }
        }

        [Description("The back color appearence of the left panel.")]
        [Category("Appearance")]
        public virtual ColorPair LeftPair
        {
            get
            {
                return this.leftPair;
            }
            set
            {
                if (this.leftPair == value)
                {
                    return;
                }
                this.leftPair = value;
                this.Invalidate(this.LeftRectangle);
            }
        }

        [Category("Appearance")]
        [Description("The background image of the panel.")]
        public virtual Image BindingImage
        {
            get
            {
                return this.bindingImage;
            }
            set
            {
                if (value != this.bindingImage)
                {
                    this.bindingImage = value;
                    this.OnBindingImageChanged();
                    this.Invalidate();
                }
            }
        }

        protected virtual Rectangle LeftRectangle
        {
            get
            {
                return new Rectangle(0, 0, 164, this.Height);
            }
        }

        [Category("Appearance")]
        [DefaultValue("Enter a brief description of the wizard here.")]
        [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
        [Description("The subtitle of the step.")]
        public virtual string Subtitle
        {
            get
            {
                return this.subtitle;
            }
            set
            {
                if (this.subtitle == value)
                {
                    return;
                }
                Region refreshRegion = this.GetTextBounds();
                this.subtitle = value;
                refreshRegion.Union(this.GetTextBounds());
                Invalidate(refreshRegion);
                return;
            }
        }

        [DefaultValue("Welcome to the DemoWizard.")]
        [Description("The title of the step.")]
        [Category("Appearance")]
        [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
        public virtual string Title
        {
            get
            {
                return this.title;
            }
            set
            {
                if (this.title == value)
                {
                    return;
                }
                Region refreshRegion = this.GetTextBounds();
                this.title = value;
                refreshRegion.Union(this.GetTextBounds());
                Invalidate(refreshRegion);
            }
        }

        protected virtual bool ShouldSerializeSubtitleAppearence()
        {
            var sa = new TextAppearence();
            sa.Font = new Font("Microsoft Sans", 8.25f, GraphicsUnit.Point);
            return this.SubtitleAppearence != sa;
        }

        protected virtual bool ShouldSerializeTitleAppearence()
        {
            var ta = new TextAppearence();
            ta.Font = new Font("Verdana", 12f, FontStyle.Bold, GraphicsUnit.Point);
            return this.TitleAppearence != ta;
        }

        protected virtual void ResetTitleAppearence()
        {
            this.titleAppearence = new TextAppearence();
            this.titleAppearence.Font = new Font("Verdana", 12f, FontStyle.Bold, GraphicsUnit.Point);
        }

        protected virtual void ResetSubtitleAppearence()
        {
            this.subtitleAppearence = new TextAppearence();
            this.subtitleAppearence.Font = new Font("Microsoft Sans", 8.25f, GraphicsUnit.Point);
        }

        protected virtual bool ShouldSerializeLeftPair()
        {
            var pa = new ColorPair(Color.Orange, Color.White, 270);
            return this.leftPair != pa;
        }

        private void ResetLeftPair()
        {
            this.leftPair = new ColorPair(Color.Orange, Color.White, 270);
        }

        protected virtual bool ShouldSerializeBindingImage()
        {
            return this.BindingImage != Resources.left;
        }

        private void ResetBindingImage()
        {
            this.BindingImage = Resources.left;
        }

        protected virtual bool ShouldSerializeIcon()
        {
            return this.Icon != Resources.icon;
        }

        private void ResetIcon()
        {
            this.Icon = Resources.icon;
        }
    }
}